﻿#ifndef RECEPTION_H
#define RECEPTION_H

/*
 *  管理接受客户端连接相关内容
 *  接收连接 / 关闭连接
 *  ?如何判断客户端处于连接状态
 *
 *  On the way - 实现消息循环(用不用多线程)
 *             - 用数组 配合 functional.h 的shuffle 函数, list<Player>::iterator it.begin() 就是教官,然后每次都循环进行回合即可
 *             - 思考断线 Player 对象的处理
 *
 */

#include <iostream>
#include <string>
#include "json/json.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include "macro.h"
#include "tojson.h"
using namespace std;

//socket全局变量
sockaddr_in addr, addr_of;
sockaddr_in caddr[10];   //客户端的socket结构体
socklen_t  len=0;
int sockfd=0;

//broadcast stuff
int bcport = 0;  //广播端口

//
int readyCount=0; //设定最大连接数 max=10
int clients=0;    //记录客户端连接数
char* froms[10];  //储存客户端的IP
int fds[10];      //记录客户端连接的描述符
bool iskillall=0;       //测试用

//满员线程处理函数

int bc_thread()
{

    cout<<"~~~"<<endl;
    while(1)
    {
        if(iskillall)
        {
            int sockClient[10];
            //连接服务端
            sockaddr_in addrSvr[10]={0};
            cout<<"~~~~~~~~~~~~~~~~~~~"<<endl;
            for(int i=0;i<clients;i++)
            {
                sockClient[i]=socket(PF_INET,SOCK_STREAM,0);
                addrSvr[i].sin_family=PF_INET;
                addrSvr[i].sin_port=htons(bcport+i);
                addrSvr[i].sin_addr.s_addr=inet_addr("127.0.0.1");//(froms[i]) ;//把文本转换成 IP地址
                int tem=connect(sockClient[i],(sockaddr*)&addrSvr[i],sizeof(addrSvr[i]));
                cout<<"connect "<<i<<" "<<tem<<endl;
            }
            //测试广播
            BroadcastInfo bi;
            bi.Content="广播消息 Independent";
            bi.Remark="备用";
            char buf[4096];
            string tmp2=bi.Json(bi,buf,SERIALIZE);
            for(int i=0; i<clients; i++)
            {
                write(sockClient[i],tmp2.data(),strlen(tmp2.data()));    //反馈
                cout<<"sent "<<i<<endl;
            }
        }
        iskillall=0;
    }
}


void* callbc(void* par)  //socket 线程主被调函数
{
    bc_thread();
}

//void* task(void* par=NULL);
int task()
{
        //设置连接上限
        cout<<"请设定游戏人数(上限为10): ";
        cin>>readyCount;
        if(readyCount > 10)
        {
            cout<<"超过上限,强制设定为10!"<<endl;
            readyCount=10;
        }
        //创建 socket
        sockfd=socket(PF_INET,SOCK_STREAM,0);
        if(sockfd == EOF)
        {
                perror("socket error : ");
                exit(-1);
        }
        cout<<"打开(socket) OK!"<<endl;
        addr.sin_family=PF_INET;
        int host=0;
        cout<<"输入要使用的端口(1025 ~ 65535):";
        cin>>host;
        cout<<"输入Broadcast端口(1025 ~ 65535):";
        cin>>bcport;
        addr.sin_port=htons(host);
        addr.sin_addr.s_addr=inet_addr("127.0.0.1");
        int res=bind(sockfd,(sockaddr*)&addr,sizeof(addr));
        if(res == EOF)
        {
                perror("bind error : ");
                exit(-1);
        }
        cout<<"绑定(bind) OK!"<<endl;
        res=listen(sockfd,readyCount);
        if(res == EOF)
        {
                perror("listen error : ");
                exit(-1);
        }
        cout<<"监听(listen) OK!"<<endl;
        len=sizeof(addr);
// //////////////////////////////////////////////////
        //循环等待连接
        while(1)
        { 
            //正常连接处理
            cout<<"Remain: "<<readyCount-clients<<endl;
            fds[clients]=accept(sockfd,(sockaddr*)&caddr[clients],&len);
            froms[clients]=inet_ntoa(caddr[clients].sin_addr);  //得到客户端IP
            cout<<"客户端IP:"<<froms[clients]<<endl;             //显示客户端IP
            //测试包发送是否正常,并显示测试包内容,内容为服务端所用端口号
            char buf[4096];
            //res=read(fds[clients],buf,sizeof(buf));
            //cout<<"读到了"<<res<<"字节"<<endl<<",a   内容是"<<aa.a<<endl;
 //   ////////////////////////////////////////////
            //发送登录信息
            LoginInfo li;
            li.IsConnected=true;
            li.Remark="连接成功";
            li.NowConnectedNum=clients+1;
            li.WaitingPeopNum=readyCount - li.NowConnectedNum;
            char buf2[4096];
            string tmp = li.Json(li,buf2,SERIALIZE);
            write(fds[clients],tmp.data(),strlen(tmp.data()));    //反馈
            clients++;
        }
}

void* call(void* par)   //socket线程 主函数
{

    task();
}

#endif // RECEPTION_H



